package com.tinyproxy.common;

import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.rolling.RollingPolicy;
import ch.qos.logback.core.rolling.RolloverFailure;
import ch.qos.logback.core.rolling.helper.CompressionMode;
import ch.qos.logback.core.rolling.helper.RenameUtil;
import ch.qos.logback.core.spi.ContextAwareBase;

import java.io.File;

/**
 * Logback原生滚动日志在graalvm下问题太多，重写一份滚动策略
 *
 * @author catii
 */
public class TinyRollingPolicy extends ContextAwareBase implements RollingPolicy {

    private FileAppender<?> parent;

    private boolean started;

    private int maxIndex;
    private int minIndex;
    final String pattern;

    RenameUtil util = new RenameUtil();

    public TinyRollingPolicy(String pattern) {
        this.pattern = pattern;
    }

    @Override
    public void rollover() throws RolloverFailure {
        // Inside this method it is guaranteed that the hereto active log file is
        // closed.
        // If maxIndex <= 0, then there is no file renaming to be done.
        if (maxIndex >= 0) {
            // Delete the oldest file, to keep Windows happy.
            File file = new File(pattern.formatted(maxIndex));

            if (file.delete()) {
                System.out.println("delete...");
            }

            // Map {(maxIndex - 1), ..., minIndex} to {maxIndex, ..., minIndex+1}
            for (int i = maxIndex - 1; i >= minIndex; i--) {
                String toRenameStr = pattern.formatted(i);
                File toRename = new File(toRenameStr);
                // no point in trying to rename a nonexistent file
                if (toRename.exists()) {
                    util.rename(toRenameStr, pattern.formatted(i + 1));
                } else {
                    addInfo("Skipping roll-over for inexistent file " + toRenameStr);
                }
            }

            util.rename(getActiveFileName(), pattern.formatted(minIndex));
        }
    }

    @Override
    public String getActiveFileName() {
        return parent.rawFileProperty();
    }

    public CompressionMode getCompressionMode() {
        return CompressionMode.NONE;
    }

    public boolean isStarted() {
        return started;
    }

    public void start() {
        util.setContext(this.context);
        if (parent.isPrudent()) {
            addError("Prudent mode is not supported with FixedWindowRollingPolicy.");
            throw new IllegalStateException("Prudent mode is not supported.");
        }

        if (maxIndex < minIndex) {
            addWarn("MaxIndex (" + maxIndex + ") cannot be smaller than MinIndex (" + minIndex + ").");
            addWarn("Setting maxIndex to equal minIndex.");
            maxIndex = minIndex;
        }

        started = true;
    }

    public void stop() {
        started = false;
    }

    public void setParent(FileAppender<?> appender) {
        this.parent = appender;
    }

    public void setMaxIndex(int maxIndex) {
        this.maxIndex = maxIndex;
    }

    public void setMinIndex(int minIndex) {
        this.minIndex = minIndex;
    }
}
